#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""腾讯证券交易接口连接器
负责与腾讯证券交易平台进行底层通信，提供基础API调用功能
支持多账户管理"""

import os
import json
import time
import requests
from datetime import datetime

# 临时模拟Logger类，解决导入问题
class Logger:
    @staticmethod
    def init_logger():
        pass
    
    @staticmethod
    def log_info(msg):
        print(f"INFO: {msg}")
        
    @staticmethod
    def log_warning(msg):
        print(f"WARNING: {msg}")
        
    @staticmethod
    def log_error(msg):
        print(f"ERROR: {msg}")

from utils.security_utils import SecurityUtils

class TencentAPIConnector:
    """腾讯证券交易接口连接器
    封装与腾讯证券交易平台的底层通信，提供身份认证、数据请求等基础功能
    支持多账户管理"""
    
    # API基础配置
    API_BASE_URL = "http://qt.gtimg.cn/q="  # 腾讯行情API基础URL
    API_TIMEOUT = 30  # API调用超时时间(秒)
    RETRY_COUNT = 3  # 失败重试次数
    RETRY_INTERVAL = 1.5  # 重试间隔(秒)
    
    def __init__(self, account_id=None):
        """初始化腾讯API连接器
        
        Args:
            account_id: 账户ID，如果为None则使用默认账户
        """
        # 账户ID
        self.account_id = account_id or "default"
        
        # API凭证
        self.api_key = None
        self.api_secret = None
        self.session_token = None
        
        # 连接状态
        self.is_authenticated = False
        self.last_authentication_time = None
        
        # 请求统计
        self.request_count = 0
        self.error_count = 0
    
    def load_api_credentials(self, account_id=None):
        """从配置文件加载指定账户的API凭证（加密方式）
        
        Args:
            account_id: 账户ID，如果为None则使用当前账户ID
            
        Returns:
            bool: 加载过程是否完成（即使部分解密失败也返回True）
        """
        try:
            # 如果提供了新的账户ID，更新当前账户ID
            if account_id:
                self.account_id = account_id
                # 重置连接状态
                self.is_authenticated = False
                self.session_token = None
            
            # 加载账户凭证
            api_key, api_secret = SecurityUtils.secure_load_credentials(self.account_id)
            
            # 检查凭证是否有效
            if api_key and api_secret:
                self.api_key = api_key
                self.api_secret = api_secret
                Logger.log_info(f"成功加载账户 {self.account_id} 的API凭证，API Key: {SecurityUtils.mask_sensitive_info(api_key)}")
                return True
            else:
                # 凭证无效，尝试使用默认凭证
                Logger.log_warning(f"账户 {self.account_id} 的凭证无效或不存在，使用默认测试凭证")
                self.api_key = "demo_api_key"
                self.api_secret = "demo_api_secret"
                return True
                
        except Exception as e:
            Logger.log_error(f"加载账户 {self.account_id} 的API凭证时出现异常: {str(e)}")
            # 发生异常时也设置默认凭证，确保系统能继续运行
            self.api_key = "demo_api_key"
            self.api_secret = "demo_api_secret"
            Logger.log_warning("使用默认测试凭证")
            return True
            
    def save_api_credentials(self, api_key, api_secret, account_id=None):
        """安全保存指定账户的API凭证到配置文件
        
        Args:
            api_key: API密钥
            api_secret: API密钥密码
            account_id: 账户ID，如果为None则使用当前账户ID
            
        Returns:
            bool: 是否保存成功
        """
        try:
            # 如果提供了新的账户ID，更新当前账户ID
            if account_id:
                self.account_id = account_id
            
            # 验证输入
            if not api_key or not api_secret:
                Logger.log_error("API密钥或密码不能为空")
                return False
            
            # 安全保存凭证
            success = SecurityUtils.secure_save_credentials(self.account_id, api_key, api_secret)
            
            if success:
                # 更新当前实例的凭证
                self.api_key = api_key
                self.api_secret = api_secret
                # 重置连接状态，需要重新认证
                self.is_authenticated = False
                self.session_token = None
                Logger.log_info(f"成功保存账户 {self.account_id} 的API凭证，API Key: {SecurityUtils.mask_sensitive_info(api_key)}")
                return True
            else:
                Logger.log_error(f"保存账户 {self.account_id} 的API凭证失败")
                return False
        except Exception as e:
            Logger.log_error(f"保存账户 {self.account_id} 的API凭证异常: {str(e)}")
            return False
    
    def authenticate(self):
        """进行API身份认证
        
        Returns:
            bool: 认证是否成功
        """
        try:
            # 确保凭证已加载
            if not self.api_key or not self.api_secret:
                if not self.load_api_credentials():
                    return False
            
            # 在实际环境中，这里应该调用腾讯API的认证接口
            # 由于这是测试环境，我们模拟认证成功
            Logger.log_info(f"执行账户 {self.account_id} 的API认证...")
            
            # 模拟网络延迟
            time.sleep(0.5)
            
            # 认证成功
            self.is_authenticated = True
            self.last_authentication_time = datetime.now()
            self.session_token = f"session_{self.account_id}_{time.time()}"
            Logger.log_info(f"账户 {self.account_id} 的API认证成功")
            return True
        except Exception as e:
            Logger.log_error(f"账户 {self.account_id} 的API认证失败: {str(e)}")
            self.error_count += 1
            return False
    
    def get_stock_quote(self, stock_code):
        """获取股票实时行情
        
        Args:
            stock_code: 股票代码，如"600000"或带交易所前缀的代码"SH600000"
            
        Returns:
            dict: 股票行情数据或None
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
        
        try:
            # 不自动添加股票前缀，使用原始股票代码
            processed_stock_code = stock_code
            
            # 构建请求URL
            # 注意：这里使用腾讯公开的行情API格式，实际接口可能有所不同
            request_url = f"{self.API_BASE_URL}{processed_stock_code}"
            
            # 发送请求
            response = requests.get(request_url, timeout=self.API_TIMEOUT)
            self.request_count += 1
            
            if response.status_code == 200:
                # 解析响应数据
                # 腾讯行情API返回的是特定格式的文本，需要进行解析
                data = self._parse_quote_response(response.text)
                # 确保返回的数据使用原始的股票代码
                if data:
                    data['stock_code'] = stock_code
                return data
            else:
                Logger.log_error(f"获取行情失败，HTTP状态码: {response.status_code}")
                self.error_count += 1
                return None
        except Exception as e:
            Logger.log_error(f"获取行情异常: {str(e)}")
            self.error_count += 1
            return None
            
    def _get_mock_stock_data(self, stock_code):
        """获取模拟的股票数据作为后备方案
        
        Args:
            stock_code: 股票代码
            
        Returns:
            dict: 模拟的股票行情数据
        """
        Logger.log_info(f"使用模拟数据: {stock_code}")
        # 为不同类型的股票提供模拟数据
        mock_data = {
            "stock_name": f"模拟股票{stock_code}",
            "current_price": 10.0 + (hash(stock_code) % 100) / 10.0,
            "open_price": 9.8 + (hash(stock_code) % 100) / 10.0,
            "prev_close": 9.9 + (hash(stock_code) % 100) / 10.0,
            "high_price": 10.2 + (hash(stock_code) % 100) / 10.0,
            "low_price": 9.7 + (hash(stock_code) % 100) / 10.0,
            "volume": 1000000 + hash(stock_code) % 9000000,
            "amount": 10000000.0 + (hash(stock_code) % 90000000) / 10.0,
            # 添加分析报告所需的技术指标
            "ma5": 9.9 + (hash(stock_code) % 100) / 10.0,
            "ma10": 9.7 + (hash(stock_code) % 100) / 10.0,
            "ma20": 9.5 + (hash(stock_code) % 100) / 10.0,
            "rsi": 50.0 + (hash(stock_code) % 40) - 20,
            "macd": (hash(stock_code) % 200 - 100) / 10.0,
            "volatility": 2.5 + (hash(stock_code) % 50) / 10.0,
            "risk_level": "中等",
            "recommendation": "持有",
            "pe_ratio": 15.0 + (hash(stock_code) % 30),
            "pb_ratio": 1.8 + (hash(stock_code) % 20) / 10.0,
            "roe": 8.0 + (hash(stock_code) % 12)
        }
        return mock_data
    
    def _parse_quote_response(self, response_text):
        """解析行情响应数据
        
        Args:
            response_text: API返回的原始文本
            
        Returns:
            dict: 解析后的行情数据，如果无法解析则返回None
        """
        try:
            # 实际解析腾讯行情API返回的文本格式
            # 腾讯行情API返回格式通常为: v_SH600000="1~浦发银行~600000~8.50~8.45~8.45~15600000~132600000~..."
            import re
            
            # 提取股票代码和数据部分
            match = re.search(r'v_(\w+)="([^"]+)"', response_text)
            if not match:
                Logger.log_error("无法解析响应数据格式")
                return None
            
            stock_code = match.group(1)
            data_parts = match.group(2).split('~')
            
            # 验证数据完整性
            if len(data_parts) < 30:
                Logger.log_error(f"响应数据不完整，仅包含 {len(data_parts)} 个字段")
                # 不再自动回退到模拟数据，而是返回已解析的部分数据
                if len(data_parts) >= 8:
                    stock_data = {
                        "stock_name": data_parts[1],
                        "current_price": float(data_parts[3]),
                        "open_price": float(data_parts[4]),
                        "prev_close": float(data_parts[5]),
                        "high_price": float(data_parts[3]) if len(data_parts) > 33 else float(data_parts[3]),
                        "low_price": float(data_parts[3]) if len(data_parts) > 34 else float(data_parts[3]),
                        "volume": int(data_parts[6]),
                        "amount": float(data_parts[7])
                    }
                    Logger.log_info(f"解析 {stock_code} 的部分行情数据")
                    return stock_data
                return None
            
            # 解析腾讯API返回的数据字段
            # 字段含义参考腾讯行情API文档
            stock_data = {
                "stock_name": data_parts[1],
                "current_price": float(data_parts[3]),
                "open_price": float(data_parts[4]),
                "prev_close": float(data_parts[5]),
                "high_price": float(data_parts[33]),
                "low_price": float(data_parts[34]),
                "volume": int(data_parts[6]),
                "amount": float(data_parts[7])
            }
            
            Logger.log_info(f"成功解析 {stock_code} 的实时行情数据")
            return stock_data
        except Exception as e:
            Logger.log_error(f"解析行情响应异常: {str(e)}")
            # 不再回退到模拟数据，而是返回None
            return None
    
    def close(self):
        """关闭API连接，清理资源"""
        # 释放资源
        self.session_token = None
    
    def get_market_data(self, stock_codes):
        """获取股票行情数据（支持单个或多个股票代码）
        
        Args:
            stock_codes (str or list): 股票代码或股票代码列表，可以是带交易所前缀的代码（如"SH600000"）或纯数字代码（如"600000"）
            
        Returns:
            dict: 行情数据，以原始股票代码为键
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
        
        try:
            # 标准化输入
            if isinstance(stock_codes, str):
                stock_codes = [stock_codes]
            
            result = {}
            for code in stock_codes:
                # 使用现有的get_stock_quote方法获取单个股票数据
                data = self.get_stock_quote(code)
                if data:
                    result[code] = data
            
            return result
        except Exception as e:
            Logger.log_error(f"获取市场数据异常: {str(e)}")
            self.error_count += 1
            return None
    
    def place_order(self, stock_code, order_type, quantity, price):
        """发送交易委托下单请求
        
        Args:
            stock_code: 股票代码
            order_type: 订单类型，'buy'或'sell'
            quantity: 交易数量
            price: 交易价格
            
        Returns:
            dict: 订单响应结果或None
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
                
        try:
            # 构建请求参数
            order_params = {
                "api_key": self.api_key,
                "session_token": self.session_token,
                "stock_code": stock_code,
                "order_type": order_type,
                "quantity": quantity,
                "price": price,
                "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
            
            Logger.log_info(f"发送下单请求: {stock_code} {order_type} {quantity}股 @ {price}")
            
            # 在实际环境中，这里应该调用腾讯API的交易接口
            # 由于这是测试环境，我们模拟API调用过程
            time.sleep(0.8)  # 模拟网络延迟
            
            # 模拟API返回结果
            order_id = f"order_{int(time.time())}"
            response = {
                "success": True,
                "order_id": order_id,
                "message": "委托下单成功",
                "order_info": {
                    "order_id": order_id,
                    "stock_code": stock_code,
                    "order_type": order_type,
                    "quantity": quantity,
                    "price": price,
                    "status": "pending",
                    "create_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                }
            }
            
            self.request_count += 1
            Logger.log_info(f"下单成功，订单号: {order_id}")
            return response
        except Exception as e:
            error_message = f"下单API调用失败: {str(e)}"
            Logger.log_error(error_message)
            self.error_count += 1
            return {"success": False, "message": error_message}
    
    def cancel_order(self, order_id):
        """发送撤单请求
        
        Args:
            order_id: 订单ID
            
        Returns:
            dict: 撤单响应结果或None
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
                
        try:
            # 构建请求参数
            cancel_params = {
                "api_key": self.api_key,
                "session_token": self.session_token,
                "order_id": order_id,
                "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
            
            Logger.log_info(f"发送撤单请求: {order_id}")
            
            # 模拟API调用
            time.sleep(0.5)  # 模拟网络延迟
            
            # 模拟API返回结果
            response = {
                "success": True,
                "message": "撤单成功",
                "order_id": order_id
            }
            
            self.request_count += 1
            Logger.log_info(f"撤单成功，订单号: {order_id}")
            return response
        except Exception as e:
            error_message = f"撤单API调用失败: {str(e)}"
            Logger.log_error(error_message)
            self.error_count += 1
            return {"success": False, "message": error_message}
    
    def query_order(self, order_id):
        """查询订单状态
        
        Args:
            order_id: 订单ID
            
        Returns:
            dict: 订单详情或None
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
                
        try:
            # 构建请求参数
            query_params = {
                "api_key": self.api_key,
                "session_token": self.session_token,
                "order_id": order_id,
                "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
            
            Logger.log_info(f"查询订单状态: {order_id}")
            
            # 模拟API调用
            time.sleep(0.3)  # 模拟网络延迟
            
            # 模拟API返回结果
            response = {
                "success": True,
                "order_info": {
                    "order_id": order_id,
                    "status": "filled",
                    "filled_quantity": 100,
                    "filled_price": 8.5,
                    "update_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                }
            }
            
            self.request_count += 1
            return response
        except Exception as e:
            error_message = f"订单查询API调用失败: {str(e)}"
            Logger.log_error(error_message)
            self.error_count += 1
            return {"success": False, "message": error_message}
            
    def get_account_info(self):
        """获取账户信息
        
        Returns:
            dict: 账户信息，包括总资产、可用资金等
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
                
        try:
            Logger.log_info("获取账户信息")
            
            # 模拟API调用延迟
            time.sleep(0.5)
            
            # 返回模拟数据
            response = {
                "success": True,
                "account_info": {
                    "total_asset": 500000.00,
                    "available_cash": 150000.00,
                    "market_value": 350000.00,
                    "total_profit": 50000.00,
                    "profit_rate": 11.11,
                    "update_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                }
            }
            
            self.request_count += 1
            return response
        except Exception as e:
            error_message = f"获取账户信息失败: {str(e)}"
            Logger.log_error(error_message)
            self.error_count += 1
            return {"success": False, "message": error_message}
            
    def get_positions(self):
        """获取持仓信息
        
        Returns:
            dict: 持仓信息，以股票代码为键
        """
        if not self.is_authenticated:
            if not self.authenticate():
                return None
                
        try:
            Logger.log_info("获取持仓信息")
            
            # 模拟API调用延迟
            time.sleep(0.5)
            
            # 返回模拟数据
            response = {
                "success": True,
                "positions": {
                    "SH600000": {
                        "stock_name": "浦发银行",
                        "quantity": 1000,
                        "cost_price": 8.5,
                        "current_price": 9.2
                    },
                    "SZ000001": {
                        "stock_name": "平安银行",
                        "quantity": 800,
                        "cost_price": 12.3,
                        "current_price": 13.1
                    },
                    "SH601318": {
                        "stock_name": "中国平安",
                        "quantity": 500,
                        "cost_price": 45.8,
                        "current_price": 48.3
                    }
                },
                "update_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
            
            self.request_count += 1
            return response
        except Exception as e:
            error_message = f"获取持仓信息失败: {str(e)}"
            Logger.log_error(error_message)
            self.error_count += 1
            return {"success": False, "message": error_message}